import io
import json
import logging
import os
import textwrap
from datetime import datetime, timedelta

from PIL import Image, ImageDraw, ImageFont
from flask import Flask, send_file, make_response, request

from DayHandle import get_daily_star, get_current_date, get_holidays
from ImgHandle import get_image_data, get_oss_image_url, get_cos_image_url

app = Flask(__name__)


@app.before_request
def check_referer():
    allowed_domains = ['']
    referer = request.headers.get('Referer')
    if referer:
        referer_domain = referer.split('//')[-1].split('/')[0]
        if not any(referer_domain.endswith(domain) for domain in allowed_domains):
            return "Forbidden 你小子还想用我图片！", 403


@app.route('/daily', methods=['GET'])
def image_with_text():
    stars_file_path = f'resource/stars.json'

    if not os.path.exists(stars_file_path):
        os.makedirs(os.path.dirname(stars_file_path), exist_ok=True)
        logging.error(f"文件{stars_file_path} 不存在")
        best_star_json = get_daily_star()
        image = get_image_data(get_cos_image_url())
    else:
        try:
            with open(stars_file_path, 'r', encoding='utf-8') as r:
                already_data = json.load(r)
                if datetime.now().strftime("%Y-%m-%d") in already_data.get('date', []):
                    best_star_json = already_data
                    image = get_image_data(best_star_json['imageUrl'])
                else:
                    best_star_json = get_daily_star()
                    image = get_image_data(get_cos_image_url())
        except json.decoder.JSONDecodeError:
            logging.error(f"文件{stars_file_path} 解析错误")
            best_star_json = get_daily_star()
            image = get_image_data(get_cos_image_url())

    current_date = get_current_date()  # 获取当前日期
    horoscope = best_star_json['horoscope']  # 幸运星座
    shorts = best_star_json['shorts']  # 概括
    contentAll = best_star_json['contentAll']  # 说的话
    luckyTime = best_star_json['lucklyTime']  # 时刻

    # 计算各部分的高度
    font_star = ImageFont.truetype("ttf/站酷高端黑修订版.ttf", 170)
    font_medium = ImageFont.truetype("ttf/NotoSansSC-Bold.otf", 50)
    font_date = ImageFont.truetype("ttf/NotoSansSC-Bold.otf", 60)
    font_content = ImageFont.truetype("ttf/NotoSansSC-Bold.otf", 49)

    horoscope_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), horoscope, font=font_star)
    shorts_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), shorts, font=font_medium)
    date_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), current_date, font=font_date)
    luckyTime_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), luckyTime, font=font_medium)
    contentAll_wrapped = textwrap.fill(contentAll, width=20)
    contentAll_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), contentAll_wrapped,
                                                                        font=font_content)
    bottom_text_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), "仅供娱乐|相信科学|请勿迷信",
                                                                         font=font_medium)

    total_height = (
            horoscope_bbox[3] +  # 幸运星座
            (shorts_bbox[3] - shorts_bbox[1]) +  # 概括
            (date_bbox[3] - date_bbox[1]) +  # 日期
            (luckyTime_bbox[3] - luckyTime_bbox[1]) +  # 时刻
            (contentAll_bbox[3] - contentAll_bbox[1]) +  # 说的话
            image.height +
            (bottom_text_bbox[3] - bottom_text_bbox[1]) +  # 底部
            250  # 横线
    )

    # 新建画布
    canvas = Image.new('RGB', (1080, int(total_height)), color=(255, 255, 255))
    draw = ImageDraw.Draw(canvas)

    # 幸运星座
    draw.text((40, 25), horoscope, font=font_star, fill=(0, 0, 0))
    y_offset = horoscope_bbox[3] + 50

    # 概括
    draw.text((40, y_offset), shorts, font=font_medium, fill=(21, 155, 255))
    y_offset += (shorts_bbox[3] - shorts_bbox[1])

    # 日期
    draw.text((600, 15), current_date, font=font_date, fill=(0, 0, 0))
    y_offset += (date_bbox[3] - date_bbox[1])

    # 时刻
    draw.text((600, y_offset - 200), luckyTime, font=font_medium, fill=(239, 80, 150))
    y_offset += (luckyTime_bbox[3] - luckyTime_bbox[1])

    # 横线
    draw.line([(40, y_offset - 30), (1050, y_offset - 30)], fill=(128, 128, 128), width=3)
    y_offset += 20

    # 说的话
    draw.text((60, y_offset), contentAll_wrapped, font=font_content, fill=(0, 0, 0))
    y_offset += (contentAll_bbox[3] - contentAll_bbox[1])

    # 图片
    if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
        # 如果图像有透明度通道，使用透明度掩码
        canvas.paste(image, (70, int(y_offset + 100)), image)
    else:
        # 如果图像没有透明度通道，直接粘贴
        canvas.paste(image, (70, int(y_offset + 100)))

    y_offset += image.height

    # 底部的话
    draw.text((60, y_offset + 130), "仅供娱乐|相信科学|请勿迷信", font=font_medium, fill=(128, 128, 128))
    y_offset += (bottom_text_bbox[3] - bottom_text_bbox[1])

    # 竖线
    draw.line([(20, 0), (20, total_height)], fill=(128, 128, 128), width=5)

    # 将图片转换为字节流
    img_byte_arr = io.BytesIO()
    canvas.save(img_byte_arr, format='JPEG')
    img_byte_arr = img_byte_arr.getvalue()

    # 计算剩余时间直到午夜
    now = datetime.now()
    tomorrow = now + timedelta(days=1)
    midnight = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 0, 0, 0)
    seconds_until_midnight = (midnight - now).total_seconds()

    response = make_response(send_file(io.BytesIO(img_byte_arr), mimetype='image/jpeg'))
    response.headers['Cache-Control'] = f'public, max-age={int(seconds_until_midnight)}'
    return response


@app.route('/holidays', methods=['GET'])
def image_with_holidays():
    holidays = get_holidays()

    # 新建画布
    canvas = Image.new("RGB", (3400, 3050), color=(255, 255, 255))
    draw = ImageDraw.Draw(canvas)

    # 绘制背景图片
    background = Image.open("img/hoshino.png").resize((3500, 3050), Image.Resampling.LANCZOS)
    canvas.paste(background, (0, 0))

    # 设置字体
    font_holiday = ImageFont.truetype("ttf/汉堡包手机字体.ttf", 140)
    font_today = ImageFont.truetype("ttf/汉堡包手机字体.ttf", 80)

    holiday_x = 1985
    y_offset = 770

    # 绘制今天日期
    draw.text((40, 20), get_current_date(), font=font_today, fill=(0, 0, 0))

    # 绘制节假日信息
    for i, (holiday_name, days_diff) in enumerate(holidays.items()):
        # 构建节假日信息文本
        if len(holiday_name) == 2:
            holiday_name = f'{holiday_name[0]}　{holiday_name[1]}'
        holiday_text = f'{holiday_name}     快　乐！' if days_diff == 0 else f"{holiday_name}      {days_diff:3}天"

        holiday_y = y_offset + i * 210
        draw.text((holiday_x, holiday_y), holiday_text, font=font_holiday, fill=(0, 0, 0))

    img_byte_arr = io.BytesIO()
    canvas.save(img_byte_arr, format='JPEG')
    img_byte_arr = img_byte_arr.getvalue()

    # 计算剩余时间直到午夜
    now = datetime.now()
    tomorrow = now + timedelta(days=1)
    midnight = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 0, 0, 0)
    seconds_until_midnight = (midnight - now).total_seconds()

    response = make_response(send_file(io.BytesIO(img_byte_arr), mimetype='image/jpeg'))
    response.headers['Cache-Control'] = f'public, max-age={int(seconds_until_midnight)}'
    return response


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)
